package com.fsh.http.request ;

import java.io.IOException ;
import java.io.InputStream ;
import java.net.HttpURLConnection ;
import java.net.URL ;
import java.util.List ;
import java.util.Map ;

import com.fsh.http.exception.HttpException ;
import com.fsh.http.util.Constant ;
import com.fsh.http.util.Util ;

/**
 * 请求的基类 Description: 
 * 
 * @author 80002165
 * @date 2017年1月17日 下午1:52:07
 */
public abstract class Request<T extends Request> {
    protected final HttpURLConnection connection ;
    protected final String url ;
    private boolean connected ;
    
    public Request(String url, int connectTimeout, int readTimeout) {
        try {
            this.url = url ;
            this.connection = (HttpURLConnection) (new URL(url)).openConnection() ;
            this.connection.setConnectTimeout(connectTimeout) ;
            this.connection.setReadTimeout(readTimeout) ;
        } catch (IOException e) {
            throw new HttpException("Failed URL: " + url, e) ;
        }
    }
    
    public Request<T> setheader(String name, String value) {
        this.connection.setRequestProperty(name, value) ;
        return this ;
    }
    
    protected Request connect() {
        if (!this.connected) {
            Request t = this.doConnect() ;
            this.connected = true ;
            return t ;
        } else {
            return this ;
        }
    }
    /**
     * 设置URL用于输入/输出的标识
     * 默认都为true
     * @author 80002165
     * @date 2017年1月17日 下午4:35:13
     */
    protected void defDoInputOrOutput(){
        setDoInput(true);
        setDoOutput(true);
        setUseCache(false) ;
    }
    
    protected void setDoInput(boolean flag){
        this.connection.setDoInput(flag);
    }
    
    protected void setDoOutput(boolean flag){
        this.connection.setDoOutput(flag);
    }
    
    protected void setUseCache(boolean flag){
        this.connection.setUseCaches(flag);
    }
    
    protected abstract T doConnect() ;
    
    public Map<String, List<String>> getHeader() {
        return this.connection.getHeaderFields() ;
    }
    
    public void dispose() {
        byte[] bytes = new byte[1024];
        try {
            InputStream ignore = this.connection.getInputStream();
            if (ignore != null) {
                while (true) {
                    if (ignore.read(bytes) <= 0) {
                        ignore.close();
                        break;
                    }
                }
            }
        } catch (Exception var5) {
            try {
                InputStream ignoreToo = this.connection.getErrorStream();
                if (ignoreToo != null) {
                    while (true) {
                        if (ignoreToo.read(bytes) <= 0) {
                            ignoreToo.close();
                            break;
                        }
                    }
                }
            } catch (IOException var4) {
                ;
            }
        }
    }
    
    public int responseCode() {
        try {
            this.connect() ;
            return this.connection.getResponseCode() ;
        } catch (IOException e) {
            throw new HttpException("Failed url：" + this.url, e) ;
        }
    }
    
    public String responseMessage() {
        try {
            this.connect() ;
            return this.connection.getResponseMessage() ;
        } catch (IOException e) {
            throw new HttpException("Failed url：" + this.url, e) ;
        }
    }
    
    public byte[] resultByte() {
        InputStream is = null ;
        try {
            this.connect() ;
            is = this.connection.getInputStream() ;
            int readLen = 0 ;
            int allLen = 0 ;
            byte[] cache = new byte[64] ;
            byte[] resultByte = new byte[is.available()] ;
            while ((readLen = is.read(cache)) != -1) {
                for (int i = 0; i < readLen; i++) {
                    resultByte[i + allLen] = cache[i] ;
                }
                allLen += readLen ;
            }
            return resultByte ;
        } catch (IOException e) {
            throw new HttpException("Failed url：" + this.url, e) ;
        } finally {
            this.dispose();
        }
    }
    
    public String resultText(){
        return resultTest(Constant.DEF_ENCODING) ;
    }
    
    public String resultTest(String encoding){
        try {
            this.connect() ;
            String result = this.responseCode() >= 400 ? Util.read(this.connection.getErrorStream()) :Util.read(this.connection.getInputStream(), encoding) ;
            return result ;
        } catch (IOException e) {
           throw new HttpException("Failed url：" + this.url, e) ;
        }finally{
            this.dispose(); 
        }
        
    }
}
